<?php

declare(strict_types=1);
/**
 * This file is part of habo_new_media.
 *
 * @link     https://www.berlen.cn/
 * @contact  tech@berlen.cn
 * @license  http://gitlab.rehou.cn/habo/habo_new_media/-/blob/master/README.md
 */
namespace app\service\cost;

use app\enum\ServiceCostEnum;
use app\model\TaskAccountModel;
use app\service\BaseService;
use app\service\cost\flow\AccountService as CostAccountService;
use app\service\cost\flow\PictureService;
use app\service\cost\flow\VideoService;
use think\Collection;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Model;

final class TaskAccountService extends BaseService
{
    /**
     * 根据任务类型获取服务.
     * @param int $taskType 任务类型
     * @return bool|CostAccountService|PictureService|VideoService
     */
    public static function getCostFlowService(int $taskType = 0)
    {
        if ($taskType == ServiceCostEnum::TASK_TYPE_ACCOUNT) {
            return new CostAccountService();
        }
        if ($taskType == ServiceCostEnum::TASK_TYPE_VIDEO) {
            return new VideoService();
        }
        if ($taskType == ServiceCostEnum::TASK_TYPE_PICTURE) {
            return new PictureService();
        }
        return self::setError('未知任务类型');
    }

    /**
     * 根据媒体任务类型获取redis_key.
     * @param int $taskType 任务类型
     * @param int $mediaId 媒体id
     * @param int $date 日期
     * @return array|string|string[]
     */
    public static function getTaskRedisKey(int $taskType = 0, int $mediaId = 0, int $date = 0)
    {
        $key = '';
        if (isset(ServiceCostEnum::TASK_REDIS_KEY[$taskType])) {
            $key = str_replace(['{media}', '{date}'], [$mediaId, $date], ServiceCostEnum::TASK_REDIS_KEY[$taskType]);
        }
        return $key;
    }

    /**
     * 根据媒体任务类型获取redis_key.
     * @param int $taskType 任务类型
     * @param int $mediaId 媒体id
     * @param int $date 日期
     * @return array|string|string[]
     */
    public static function getRecallTaskRedisKey(int $taskType = 0, int $mediaId = 0, int $date = 0)
    {
        $key = '';
        if (isset(ServiceCostEnum::TASK_RECALL_REDIS_KEY[$taskType])) {
            $key = str_replace(['{media}', '{date}'], [$mediaId, $date], ServiceCostEnum::TASK_RECALL_REDIS_KEY[$taskType]);
        }
        return $key;
    }

    /**
     * 获取redis锁key.
     */
    public static function getLockRedisKey(TaskAccountModel $model): string
    {
        return 'task:lock:' . $model->getKey();
    }

    /**
     * 新增task_account表数据.
     * @param array $params 表参数
     * @return bool|TaskAccountModel
     */
    public static function insertTaskAccountData(array $params = [])
    {
        // 验证字段
        if (empty($params['client_id'])) {
            return self::setError('客户id不能为空');
        }
        if (empty($params['account_id']) || empty($params['advertiser_id'])) {
            return self::setError('账户id不能为空');
        }
        if (empty($params['media_id'])) {
            return self::setError('媒体id不能为空');
        }
        if (empty($params['stat_date'])) {
            return self::setError('日期不能为空');
        }
        if (empty($params['type'])) {
            return self::setError('类型不能为空');
        }
        if (! isset($params['status'])) {
            return self::setError('状态不能为空');
        }
        if (! in_array($params['status'], array_keys(ServiceCostEnum::TASK_STATUS_ARR))) {
            return self::setError('状态类型错误');
        }
        try {
            $model = new TaskAccountModel();
            $model->setAttrs($params);
            $model->save();
            return $model;
        } catch (\Exception $e) {
            return self::setError('插入task_account表失败：' . $e->getMessage());
        }
    }

    /**
     * 更新task_account表数据.
     * @param TaskAccountModel $model 任务模型
     * @param array $params 修改参数
     */
    public static function updateTaskAccountData(TaskAccountModel $model, array $params = []): bool
    {
        if (! $model->getKey()) {
            return self::setError('更新task_account表失败：表数据不存在');
        }
        // 验证字段
        $data = [];
        // 状态验证
        if (! empty($params['status'])) {
            if (! in_array($params['status'], array_keys(ServiceCostEnum::TASK_STATUS_ARR))) {
                return self::setError('状态类型错误');
            }
            $data['status'] = $params['status'];
        }
        if (empty($data)) {
            return self::setError('参数不能为空');
        }
        try {
            $model->setAttrs($params);
            $model->save();
            return true;
        } catch (\Exception $e) {
            return self::setError('更新task_account表失败：' . $e->getMessage());
        }
    }

    /**
     * 删除task_account表数据.
     * @param int $id 表id
     */
    public static function deleteTaskAccountData(int $id = 0): bool
    {
        try {
            $taskModel = (new TaskAccountModel())->find($id);
            if (! $taskModel->getKey()) {
                return self::setError('删除task_account表失败：数据不存在');
            }
            return $taskModel->delete();
        } catch (\Exception $e) {
            return self::setError('删除task_account表失败：' . $e->getMessage());
        }
    }

    /**
     * 获取task_account表模型.
     * @param int $id 表id
     * @return null|array|mixed|Model|TaskAccountModel
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public static function getTaskAccountModel(int $id = 0)
    {
        return (new TaskAccountModel())->find($id);
    }

    /**
     * 设置执行次数+1.
     * @param TaskAccountModel $model 任务模型
     */
    public static function setExecuteNum(TaskAccountModel $model)
    {
        if (! $model->getKey()) {
            return self::setError('task_account表数据不存在');
        }
        return $model->inc('execute_num', 1)->update();
    }

    /**
     * 获取task_account任务.
     * @param int $type 任务类型
     * @param int $mediaId 媒体id
     * @param int $date 日期
     * @return array|Collection|TaskAccountModel[]
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function getTaskAccounts(int $type = 0, int $mediaId = 0, int $date = 0)
    {
        $where = [
            ['media_id', '=', $mediaId],
            ['stat_date', '=', $date],
            ['type', '=', $type],
            ['status', '<>', ServiceCostEnum::TASK_STATUS_SUCCESS],
        ];
        return (new TaskAccountModel())->where($where)->select();
    }

    /**
     * 判断脚本今天是否已经执行完毕.
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function isTodayTaskDone(int $taskType = 0, int $mediaId = 0, int $date = 0): bool
    {
        $isNo = (new TaskAccountModel())->where('type', $taskType)
            ->where('media_id', $mediaId)
            ->where('stat_date', $date)
            ->where('status', ServiceCostEnum::TASK_STATUS_WAIT)
            ->find();
        if ($isNo) {
            return false;
        }
        return true;
    }
}
